from ctypes import *
import skf_api as skf_def  # 导入封装定义的模块，这里起了别名skf_def方便使用

# 加载动态库
skfapi_dll = cdll.LoadLibrary("mtoken_gm3000.dll")
# 设置函数原型
skf_def.set_function_prototypes(skfapi_dll)

def main():
    ulRslt = skf_def.ULONG(skf_def.SAR_OK)
    hdev = skf_def.HANDLE(None)
    happ = skf_def.HANDLE(None)
    hcont = skf_def.HANDLE(None)
    hkey = skf_def.HANDLE(None)
    szDevName = create_string_buffer(256)
    szAppName = create_string_buffer(256)
    szContName = create_string_buffer(256)
    pUserPin = b"123456"
    ulDevNameLen = skf_def.ULONG(256)
    ulAppNameLen = skf_def.ULONG(256)
    ulContNameLen = skf_def.ULONG(256)
    ulRetryCount = skf_def.ULONG(0)
    ulHashDataLen = skf_def.ULONG(256)
    ecc_pub = skf_def.ECCPUBLICKEYBLOB()
    ecc_sign = skf_def.ECCSIGNATUREBLOB()
    ulEccpubLen = skf_def.ULONG(sizeof(skf_def.ECCPUBLICKEYBLOB))
    # bp = skf_def.BLOCKCIPHERPARAM()
    pappname = szAppName
    idlen = 16
    pdevname = szDevName
    pcontname = szContName
    # 变量类型转换：BYTE *pbData 同时需要改变上面的c_ubyte为POINTER(c_ubyte)。
    pHashData = create_string_buffer(256)
    pHashDataPointer = cast(pHashData, POINTER(c_ubyte))
    pubid = b"1234567812345678"
    # 获取pubid的长度
    pubid_len = len(pubid)
    # 创建一个c_ubyte类型的数组，长度与pubid字节串长度一致
    pubid_array = (c_ubyte * pubid_len)(*pubid)
    psrcdata = b"1234567812345678"
    psrcdata_len = len(psrcdata)
    psrcdata_array = (c_ubyte * psrcdata_len)(*psrcdata)


    # 调用SKF_EnumDev函数
    ulRslt.value = skfapi_dll.SKF_EnumDev(skf_def.BOOL(True), szDevName, byref(ulDevNameLen))
    if ulRslt.value!= skf_def.SAR_OK:
        return
    # 调用SKF_ConnectDev函数
    ulRslt.value = skfapi_dll.SKF_ConnectDev(pdevname, byref(hdev))
    if ulRslt.value!= skf_def.SAR_OK:
        return
    # 调用SKF_EnumApplication函数
    ulRslt.value = skfapi_dll.SKF_EnumApplication(hdev, szAppName, byref(ulAppNameLen))
    if ulRslt.value!= skf_def.SAR_OK:
        return
    # 调用SKF_OpenApplication函数
    ulRslt.value = skfapi_dll.SKF_OpenApplication(hdev, pappname, byref(happ))
    if ulRslt.value!= skf_def.SAR_OK:
        return
    # 调用SKF_VerifyPIN函数
    ulRslt.value = skfapi_dll.SKF_VerifyPIN(happ, skf_def.ULONG(skf_def.USER_TYPE), pUserPin, byref(ulRetryCount))
    if ulRslt.value!= skf_def.SAR_OK:
        return
    # 调用SKF_EnumContainer函数
    ulRslt.value = skfapi_dll.SKF_EnumContainer(happ, szContName, byref(ulContNameLen))
    if ulRslt.value!= skf_def.SAR_OK:
        return
    # 调用SKF_OpenContainer函数
    ulRslt.value = skfapi_dll.SKF_OpenContainer(happ, pcontname, byref(hcont))
    if ulRslt.value!= skf_def.SAR_OK:
        return



    # 修正此处，添加正确的参数传递
    buffer_size = skf_def.ULONG(1024)  # 可以根据实际情况调整缓冲区大小
    file_list_buffer = create_string_buffer(buffer_size.value)
    file_name = file_list_buffer
    # [HANDLE, ctypes.c_char_p, ctypes.POINTER(ULONG)]
    ulRslt.value = skfapi_dll.SKF_EnumFiles(happ, file_list_buffer, byref(buffer_size))
    if ulRslt.value != skf_def.SAR_OK:
        return
    print("buffer_size: ",buffer_size)
    print("file_list_buffer: ",file_list_buffer)


    # # 创建文件测试
    file_name_create = b"test"
    file_size_create = 1024
    read_rights_create = 255
    write_rights_create = 255
    ulRslt.value = skfapi_dll.SKF_CreateFile(happ, file_name_create, file_size_create, read_rights_create,
                                             write_rights_create)
    if ulRslt.value == skf_def.SAR_OK:
        print("文件创建成功")
    else:
        print(f"文件创建失败，错误码: {ulRslt.value}")

    # 新增：调用SKF_GetFileInfo函数获取文件信息
    file_info = skf_def.FILEATTRIBUTE()
    # [HANDLE, ctypes.c_char_p, ctypes.POINTER(FILEATTRIBUTE)]
    ulRslt.value = skfapi_dll.SKF_GetFileInfo(happ, file_name_create, byref(file_info))
    if ulRslt.value == skf_def.SAR_OK:
        print(f"文件名: {file_info.FileName.decode('utf-8')}")
        print(f"文件大小: {file_info.FileSize}")
        print(f"读权限: {file_info.ReadRights}")
        print(f"写权限: {file_info.WriteRights}")
    else:
        print(f"获取文件信息失败，错误码: {ulRslt.value}")

    # 写入文件测试
    offset_write = 0
    # 创建一个c_ubyte类型的数组，长度与pubid字节串长度一致
    data = b"1234567812345678"
    data_len = len(data)
    data_array = (c_ubyte * data_len)(*data)

    ulRslt.value = skfapi_dll.SKF_WriteFile(happ, file_name_create, offset_write, data_array, len(data_array))
    if ulRslt.value == skf_def.SAR_OK:
        print("文件写入成功")
    else:
        print(f"文件写入失败，错误码: {ulRslt.value}")

    offset_read = 0
    size_read = 16
    buffer = (skf_def.ctypes.c_ubyte * size_read)()  # 创建一个ctypes.c_ubyte类型的数组，用于存储读取的字节数据
    buffer_pointer = cast(buffer, POINTER(skf_def.ctypes.c_ubyte))
    actual_size_read = skf_def.ULONG(size_read)  # 创建一个ULONG类型变量，用于接收实际读取长度
    ulRslt.value = skfapi_dll.SKF_ReadFile(happ, file_name_create, offset_read, size_read, buffer_pointer, byref(actual_size_read))
    if ulRslt.value == skf_def.SAR_OK:
        print("文件读取成功，内容（十六进制表示）:", [hex(byte) for byte in buffer[:actual_size_read.value]])  # 以十六进制形式打印读取到的字节数据，根据实际读取长度截取
    else:
        print(f"文件读取失败，错误码: {ulRslt.value}")

    # 删除文件测试
    ulRslt.value = skfapi_dll.SKF_DeleteFile(happ, file_name_create)
    if ulRslt.value == skf_def.SAR_OK:
        print("文件删除成功")
    else:
        print(f"文件删除失败，错误码: {ulRslt.value}")


    # 关闭相关句柄和释放资源，对应原来C代码中的清理部分
    if hkey:
        skfapi_dll.SKF_CloseHandle(hkey)
    if hcont:
        skfapi_dll.SKF_CloseContainer(hcont)
    if happ:
        skfapi_dll.SKF_CloseApplication(happ)
    if hdev:
        skfapi_dll.SKF_DisConnectDev(hdev)


if __name__ == "__main__":
    main()